package other.up.modbus.util;

import com.serotonin.io.serial.SerialParameters;
import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.ip.IpParameters;
import com.serotonin.modbus4j.msg.*;
import com.serotonin.util.queue.ByteQueue;

import java.util.Arrays;

public class ModbusService {

    //MODBUS网络上从站地址

    private final static int SLAVE_ADDRESS=1;

    //串行口波特率

    private final static int BAUD_RATE = 9600;

    public static void modbusWTCP(String ip, int port, int slaveId, int start, short[] values) {


      ModbusFactory modbusFactory = new ModbusFactory();
      // 设备ModbusTCP的Ip与端口，如果不设定端口则默认为502  
      IpParameters params = new IpParameters();
      params.setHost(ip);  
      if (502 != port) {  
          params.setPort(port);  
      }// 设置端口，默认502  
      ModbusMaster tcpMaster = null;
      // 参数1：IP和端口信息 参数2：保持连接激活  
      tcpMaster = modbusFactory.createTcpMaster(params, true);  
      try {  
          tcpMaster.init();  
          System.out.println("===============" + 1111111);  
      } catch (ModbusInitException e) {
          // System.out.println("11111111111111=="+"此处出现问题了啊!");  
          // 如果出现了通信异常信息，则保存到数据库中  
           //CommunityExceptionRecord cer = new CommunityExceptionRecord();  
          //cer.setDate(new Date());  
          //cer.setIp(ip);  
          // cer.setRemark(bgName+"出现连接异常");  
          // batteryGroupRecordService.saveCommunityException(cer);  
      }  
      try {
          WriteRegistersRequest request = new WriteRegistersRequest(slaveId, start, values);
          WriteRegistersResponse response = (WriteRegistersResponse) tcpMaster.send(request);
        /*  WriteRegisterRequest request = new WriteRegisterRequest(slaveId, start, 26);
          WriteRegisterResponse response = (WriteRegisterResponse) tcpMaster.send(request);*/
          if (response.isException()) {
              System.out.println("Exception response: message=" + response.getExceptionMessage());
          }
          else {
              System.out.println("Success");
          }
      } catch (ModbusTransportException e) {
          e.printStackTrace();  
      }  
  }  
    
  public static ByteQueue modbusTCP(String ip, int port, int start, int readLenth) {
      ModbusFactory modbusFactory = new ModbusFactory();  
      // 设备ModbusTCP的Ip与端口，如果不设定端口则默认为502  
      IpParameters params = new IpParameters();  
      params.setHost(ip);  
      if(502!=port){params.setPort(port);}//设置端口，默认502  
      ModbusMaster tcpMaster = null;  
          tcpMaster = modbusFactory.createTcpMaster(params, true);  
          try {  
              tcpMaster.init();  
              System.out.println("==============="+1111111);  
          } catch (ModbusInitException e) {  
              return null;  
          }  
          ModbusRequest modbusRequest=null;
          try {  
              modbusRequest = new ReadHoldingRegistersRequest(1, start, readLenth);
          } catch (ModbusTransportException e) {  
              e.printStackTrace();  
          }  
          ModbusResponse modbusResponse=null;
          try {  
              modbusResponse = tcpMaster.send(modbusRequest);  
          } catch (ModbusTransportException e) {  
              e.printStackTrace();  
          }  
          ByteQueue byteQueue= new ByteQueue(12);
          modbusResponse.write(byteQueue);
          System.out.println("功能码:"+modbusRequest.getFunctionCode());  
          System.out.println("从站地址:"+modbusRequest.getSlaveId());  
          System.out.println("收到的响应信息大小:"+byteQueue.size());  
          System.out.println("收到的响应信息值:"+byteQueue);
          return byteQueue;  
  }



  

  public static void main(String[] args) throws Exception {



      //ModbusService.modbusTCP("127.0.0.1",502,0,2);
  ModbusService.modbusWTCP("127.0.0.1",502,1,0,new short[]{1,2,3});
     System.out.println("serial Port~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`");

      SerialParameters serialParameters = new SerialParameters();

      //设定MODBUS通讯的串行口

      serialParameters.setCommPortId("COM3");

      //设定成无奇偶校验

      serialParameters.setParity(0);

      //设定成数据位是8位

      serialParameters.setDataBits(7);

      //设定为1个停止位

      serialParameters.setStopBits(1);

      serialParameters.setPortOwnerName("Numb nuts");

      //串行口上的波特率

      serialParameters.setBaudRate(BAUD_RATE);

      ModbusFactory modbusFactory = new ModbusFactory();

      ModbusMaster master = modbusFactory.createRtuMaster(serialParameters);
      //ModbusMaster master = modbusFactory.createAsciiMaster(serialParameters);

      try {

          master.init();

          //readDiscreteInputTest(master,SLAVE_ADDRESS,0,8);

          //writeRegistersTest(master,SLAVE_ADDRESS, 0, new short[]{12345,0xb,0xc,0xd,0xe,0x9, 0x8, 0x7, 0x6} );
          //writeRegistersTest(master,SLAVE_ADDRESS, 0, new short[]{1,3} );
         // writeRegistersTest(master,SLAVE_ADDRESS, 0, new short[]{9} );
          // //readHoldingRegistersTest(master,SLAVE_ADDRESS,0,  5);



      }

      finally {

          master.destroy();

      }

  }

  /**

   * 读开关量型的输入信号

   * @param master 主站

   * @param slaveId 从站地址

   * @param start 起始偏移量

   * @param len 待读的开关量的个数

   */

  private static void readDiscreteInputTest(ModbusMaster master, int slaveId, int start, int len) {

      try {

          ReadDiscreteInputsRequest request = new ReadDiscreteInputsRequest(slaveId, start, len);

          ReadDiscreteInputsResponse response = (ReadDiscreteInputsResponse) master.send(request);
          System.out.println("方法码:"+request.getFunctionCode());
          ByteQueue byteQueue = new ByteQueue(1024);
          request.write(byteQueue);
          getCRC(byteQueue.toString());
          if (response.isException()) {

              System.out.println("Exception response: message=" + response.getExceptionMessage());
          }

          else {

              System.out.println(Arrays.toString(response.getBooleanData()));
          }

      }

      catch (ModbusTransportException e) {

          e.printStackTrace();

      }

  }

    /**

     * 批量写数据到保持寄存器

     * @param master 主站

     * @param slaveId 从站地址

     * @param start 起始地址的偏移量

     * @param values 待写数据

     */

    public static void writeRegistersTest(ModbusMaster master, int slaveId, int start, short[] values) {

        try {

            WriteRegistersRequest request = new WriteRegistersRequest(slaveId, start, values);

            WriteRegistersResponse response = (WriteRegistersResponse) master.send(request);
            System.out.println("写方法码:"+response.getFunctionCode());
            ByteQueue byteQueue = new ByteQueue(1024);
            response.write(byteQueue);
            getCRC(byteQueue.toString());

            if (response.isException()) {

                System.out.println("Exception response: message=" + response.getExceptionMessage());
            }

            else {

                System.out.println("Success");
            }

        }

        catch (ModbusTransportException e) {

            e.printStackTrace();

        }

    }

  /**

   * 读保持寄存器上的内容

   * @param master 主站

   * @param slaveId 从站地址

   * @param start 起始地址的偏移量

   * @param len 待读寄存器的个数

   */

  private static void readHoldingRegistersTest(ModbusMaster master, int slaveId, int start, int len) {

      try {

          ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest(slaveId, start, len);

          ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse) master.send(request);
          if (response.isException()) {

              System.out.println("Exception response: message=" + response.getExceptionMessage());
          }

          else {

              System.out.println("主机方法码:"+response.getFunctionCode());
               //etCRC(queue.toString());

          }

      }

      catch (ModbusTransportException e) {

          e.printStackTrace();

      }

  }

  private  static  void getCRC(String msg){
      msg = msg.substring(1,msg.length()-1);
      String[] strs = msg.split(",");
      StringBuffer crsStr = new StringBuffer("");
      for(int k=0;k<strs.length;k++){
          if(strs[k].length()<2){
              strs[k] = "0"+strs[k];
          }
          crsStr.append(strs[k]);
      }
      byte[] bys = ByteUtils.hexStr2Byte(crsStr.toString());
      System.out.println("待校验字符串:"+crsStr.toString());
      System.out.println("校验码:"+CRC.getCRC3(bys));
  }


}  